import {isObject} from './utils';
import {
   mutableHandlers,
   shallowReactiveHandlers,
   readonlyHandlers,
   shallowReadonlyHandlers
} from './baseHandles';

//! 响应式  api




//! 是不是 仅读  深度 柯里化  响应式api核心
//! 底层用：new Proxy 一样要拦截数据的读取修改  就是get()  set() 方法
// 如果被代理过 就不要代理哦 如果一个对象 被深度代理 又被仅读代理  如何处理？
const reactiveMap = new WeakMap(); // WeakMap 会自动垃圾回收并且key只能是对象， 不会造成内存泄漏
const readonlyMap = new WeakMap();
function createReactiveObject(target,isReadonly,baseHandle) {
   // 如果目标不是对象  就不拦截  只拦截对象类型  而ref可以拦截普通类型
   if (!isObject(target)) {
      return target;
   }

   // 如果被代理过 就不要代理哦 如果一个对象 被深度代理 又被仅读代理  如何处理？
   const proxyMap = isReadonly ? readonlyMap : reactiveMap; // 如果是仅读 就取readonlyMap，不是仅读就取reactiveMap

   // 看下是否被代理过
   const existProxy =  proxyMap.get(target);
   if (existProxy) { // 已经被代理过 直接返回
      return existProxy;
   }

   // 核心代码来了 proxy：对target这个对象进行描述  怎么描述呢？在baseHandle这里
   const proxy = new Proxy(target,baseHandle);

   // 将要代理的对象 和对应代理结果缓存
   proxyMap.set(target,proxy);

   // 把proxy返回出去
   return proxy;
}

// 不仅读  深的
export function reactive(target) {
   return createReactiveObject(target,false,mutableHandlers);
}

// 不仅读  浅的
export function shallowReactive(target) {
   return createReactiveObject(target,false,shallowReactiveHandlers);
}

// 只读 深的
export function readonly(target) {
   return createReactiveObject(target,true,readonlyHandlers);
}

// 只读 浅的
export function shallowReadonly(target) {
   return createReactiveObject(target,true,shallowReadonlyHandlers);
}